

#include "UFLTexture.h"
#include "png.h"

using namespace ufl;

TexSampler UFLTexture::defaultSampler = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };

UFLTexture::UFLTexture()
:_texPixelData(nullptr), _texWidth(0), _texHeight(0), _texDepth(0), _target(0), _texId(0)
{
	
}

UFLTexture::~UFLTexture()
{
	if (_texPixelData)
		delete _texPixelData;

	if (_texId && _texId > 0)
	{
		glDeleteTextures(1, &_texId);
	}
}

bool UFLTexture::load(const char* filename, ufl_uint32 target /* = GL_TEXTURE_2D */, TexSampler sampler /* = defaultSampler */)
{
	// 加载纹理内存数据
    png_image image;
    memset(&image, 0, sizeof(image));
    
    image.version = PNG_IMAGE_VERSION;
    if (png_image_begin_read_from_file(&image, filename)) {
        image.format = PNG_FORMAT_RGBA;
        
        ufl_uint32 imageSize = PNG_IMAGE_SIZE(image);
        ufl_uint32 imageColorMapSize = PNG_IMAGE_COLORMAP_SIZE(image);
        
        // 分配内存
        _texPixelData = new ufl_ubyte[imageSize];
        if (!png_image_finish_read(&image, nullptr, _texPixelData, 0, &imageColorMapSize)) {
            if (_texPixelData) {
                delete [] _texPixelData;
            }
        }
        
    } else {
        
    }
    
    // 保存纹理宽/高
    _texWidth = image.width;
    _texHeight = image.height;
    
    png_image_free(&image);

	// generate GL texture id
	glGenTextures(1, &_texId);
	
	if (_texId <= 0)
		return false;

	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
	glBindTexture(target, _texId);

	glTexParameteri(target, GL_TEXTURE_MAG_FILTER, sampler.mag);
	glTexParameteri(target, GL_TEXTURE_MIN_FILTER, sampler.min);
	glTexParameteri(target, GL_TEXTURE_WRAP_S, sampler.wrap_s);
	glTexParameteri(target, GL_TEXTURE_WRAP_T, sampler.wrap_t);

	// load to GL
	if (target == GL_TEXTURE_2D)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _texWidth, _texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, _texPixelData);
	}
	else if (target == GL_TEXTURE_3D)
	{

	}

	glBindTexture(target, 0);

	// set texture simpler
	_sampler = sampler;
    
	// set target
	_target = target;

	// success
	return true;
}

void UFLTexture::use()
{
	glBindTexture(_target, _texId);
}

void UFLTexture::unused()
{
	glBindTexture(_target, 0);
}